package 动态规划;

import java.util.Scanner;

/**
 * 63. 不同路径 II
 *  给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角（即 grid[0][0]）。机器人尝试移动到 右下角（即 grid[m - 1][n - 1]）。机器人每次只能向下或者向右移动一步。
 * 网格中的障碍物和空位置分别用 1 和 0 来表示。机器人的移动路径中不能包含 任何 有障碍物的方格。
 * 返回机器人能够到达右下角的不同路径数量。
 * 测试用例保证答案小于等于 2 * 109。
 * 动态规划思路：
    1：状态转移数组dp[i][j] 定义为 到达网格[i][j]位置的不同路径数量
    2：状态转移方程的推导：
        如果当前dp[i][j]==1 是障碍物。那么证明当前位置的路径数量为0， dp[i][j] = 0
        否则dp[i][j] 为其左边的路径和其上方的路径和汇总，即dp[i][j] = dp[i-1][j] + dp[i][j-1]
    3：边界条件：
        如果 obstacleGrid[0][0]==1，那么直接返回0，因为机器人无法到达左上角位置
        如果为0，那么dp[0][0] = 1

        对于第一行和第一列的格子，需要单独处理：如果某格子有障碍物，则其之后的所有路径树均为0
 */
public class L_63 {
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;
        // 初始化状态转移数组
        int[][] dp =new int[m][n];
        // 边界条件
        if (obstacleGrid[0][0] == 1){
            return 0;
        }
        dp[0][0] = 1;
        // 第一行的格子的处理
        for (int j = 1; j < n; j++){
            if (obstacleGrid[0][j] == 0){
                dp[0][j] = dp[0][j-1]; // 如果当前格子不是障碍物，则其路径和为左边格子的路径和
            }else {
                dp[0][j] = 0;
            }
        }
        // 第一列格子的处理
        for (int i = 1; i < m; i++) {
            if (obstacleGrid[i][0] == 0){
                dp[i][0] = dp[i-1][0];
            }else {
                dp[i][0] = 0;
            }
        }

        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                // 如果是障碍物，则路径数量为0
                if (obstacleGrid[i][j] == 1){
                    dp[i][j] = 0;
                }else {
                    dp[i][j] = dp[i-1][j] + dp[i][j-1];
                }
            }
        }

        return dp[m-1][n-1];
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入行数：");
        int m = scanner.nextInt();
        System.out.println("请输入列数：");
        int n = scanner.nextInt();
        int [][] grid = new int[m][n];
        for (int i = 0; i < m; i++) {
            System.out.println("请输入第" + (i + 1) + "行的元素：");
            for (int j = 0; j < n; j++) {
                System.out.println("请输入第" + (i + 1) + "行的第" + (j + 1) + "个元素：");
                grid[i][j] = scanner.nextInt();
            }
        }
        L_63 l63 = new L_63();
        int result = l63.uniquePathsWithObstacles(grid);
        System.out.println("不同路径"+ result);
    }
}
